Sentry に Rails のエラー情報を送る時に気になったことを調べたログ
2024/4/18
Sentry に Rails のエラー情報を送る設定方法は公式の方で示されている
例外処理をキャッチしてるところでエラー情報を送信したい時は Sentry.capture_exception メソッドを使ってエラーをキャプチャする必要がある
code:ruby
begin
rescue StandardError => e
Sentry.capture_exception(e)
end
Rails だとrescue_from で定義したメソッドの中に仕込むという書き方もある(実際自分もそうした)
(2024/4/19追記)
code:ruby
rescue_from StandardError, with: :handle_internal_server_error
private
def handle_internal_server_error(error)
Sentry.capture_exception(error)
# 以下省略(ログ出力したりレスポンスに入れるメッセージ用意するとかなやつ)
end
設定する中で、例外処理周りの記述についての知識が浅いなーと感じてくる
rescue_fromもなんか既存実装でいっぱい定義してくれとるな……という距離感で Railsガイド見て記憶を取り戻した
rescue_fromでExceptionやStandardErrorを指定すると、Railsでの正しい例外ハンドリングが阻害されて深刻な副作用が生じる可能性があります。よほどの理由がない限り、このような指定はおすすめできません。
StandardError に直接 rescue_from やるの非推奨なのか
StandardError クラスってどういう立ち位置なんだ?(なんか汎用的なエラーを扱う例外クラスなんだろうというぼんやりな理解でいた)
カスタム例外クラスを作る時は、大体この StandardError を継承させる書き方をしてるイメージなんだよなーと思い理由を調べてみた
Rubyで独自例外を定義するときはExceptionではなく、StandardError を継承するしきたりとなっています。
下記がビルトインのExceptionのサブクラスたちです。rescueのデフォルトがStandardError、raiseのデフォルトがRuntimeErrorとなっています。
上の例で MyExceptionは補足されない。なぜなら、rescue は第1引数で指定した例外クラスの下の階層にある例外だけを補足するけど、引数を省略すると StandardErrorクラスを指定したものとみなすからだ。MyExceptionはException直下の子クラスなので、rescue されない。
Exceptionを直接継承した自前定義の例外クラスを複数作って、それらを補足しようと思うと、いちばん上にあるExceptionごと補足するしかない。そうすると今度は、すべての例外を補足することになってしまう。例えば、exitを呼ぶと発生するSystemExitも補足されてしまう。これは恐らく望ましい動作ではない。
上記の記事2つを読んでなるほどね〜となってくる
Exception でカスタム例外クラスを継承した場合、引数省略した書き方だと StandardErrorクラスの下の階層にある例外だけを補足するので rescue されない
rescueのデフォルト引数がStandardErrorクラスであるため
Exceptionごと補足する書き方(rescue の引数にExceptionを指定)になると、すべての例外を補足することになり補足してほしくない例外も補足されてしまうのでそれは望ましい動作ではない
大前提の話として、例外クラスの先祖として Exception クラスがいてそのサブクラスとして StandardErrorクラスがある
その下に ArgumentError とか NameErrorとかよくみかける例外クラスが生えてるんだけど、全部書くと長くなるので上記の記事参考
カスタム例外の話を追いたくなって以下の記事も読んだ
小話
歴史のあるコードだと Raven という名称が Sentry関連の記述で使われてるのを見かける。なんだろうと思ってググってみたら以前の Sentry の Ruby の SDK は sentry-raven というgemがあったんだなあと知った
今は deprecated となって sentry-rubyとsentry-railsに置き換わっている